/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [Example_02_Random_Access.java]
 * Creation Date        [07-Jul-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_09_io.basic;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * 使用RandomAccess来读写文件
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class Example_02_Random_Access {

	// 每条记录100个字节
	// 40个字符=80个字节来表示姓名字符串
	// 1 double = 8个字节表示薪水
	// 3 int = 12字节表示日期的年月日
	private static final int RECORD_SIZE = 2 * DataIOHelper.NAME_SIZE + 8 + 4
			+ 4 + 4;

	/**
	 * 测试方法
	 * 
	 * @param args
	 *            命令行参数
	 */
	public static void main(String[] args) {
		DataIOHelper helper = new DataIOHelper();

		Employee[] employees = new Employee[3];
		employees[0] = new Employee("Sean", 100000, 1984, 3, 24);
		employees[1] = new Employee("CC", 100000, 1985, 4, 24);
		employees[2] = new Employee("Yang", 100000, 1986, 5, 24);

		// 保存信息
		DataOutputStream out = null;
		try {
			out = new DataOutputStream(new FileOutputStream("employee.dat"));
			for (Employee employee : employees) {
				helper.writeData(out, employee);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		// 读取信息
		RandomAccessFile in = null;
		try {
			in = new RandomAccessFile("employee.dat", "r");
			int n = (int) (in.length() / RECORD_SIZE);
			for (int i = n - 1; i >= 0; i--) {
				in.seek(i * RECORD_SIZE);
				helper.readData(in);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

}

/**
 * I/O Helper Class
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
class DataIOHelper {

	public static final int NAME_SIZE = 40;

	/**
	 * 读取固定长度的字符串
	 * 
	 * @param size
	 * @param in
	 * @return
	 * @throws IOException
	 */
	private String readFixedString(int size, DataInput in) throws IOException {
		StringBuilder builder = new StringBuilder(size);
		int i = 0;
		boolean more = true;
		while (more && i < size) {
			char ch = in.readChar();
			i++;
			if (ch == 0)
				more = false;
			else
				builder.append(ch);
		}
		in.skipBytes(2 * (size - i));
		return builder.toString();
	}

	/**
	 * 写出固定字符串, 如果字符串长度不够, 则用0补齐
	 * 
	 * @param str
	 * @param size
	 * @param out
	 * @throws IOException
	 */
	private void writeFixedString(String str, int size, DataOutput out)
			throws IOException {
		for (int i = 0; i < size; i++) {
			char ch = 0;
			if (i < str.length())
				ch = str.charAt(i);
			out.writeChar(ch);
		}
	}

	/**
	 * 读取信息
	 * 
	 * @param in
	 * @throws IOException
	 */
	public void readData(DataInput in) throws IOException {
		String name = readFixedString(NAME_SIZE, in);
		Double salary = in.readDouble();
		int year = in.readInt();
		int month = in.readInt();
		int date = in.readInt();
		Employee employee = new Employee(name, salary, year, month, date);
		System.out.println(employee);
	}

	/**
	 * 写出信息
	 * 
	 * @param out
	 * @param employee
	 * @throws IOException
	 */
	public void writeData(DataOutput out, Employee employee) throws IOException {
		writeFixedString(employee.getName(), NAME_SIZE, out);
		out.writeDouble(employee.getSalary());

		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(employee.getHireDate());
		out.writeInt(calendar.get(Calendar.YEAR));
		out.writeInt(calendar.get(Calendar.MONTH) + 1);
		out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));
	}
}
